package com.topscomm.mpm.utils;

import com.topscomm.mpm.MpmSystemConst;
import com.topscomm.mpm.pojo.MpmProjectTeamEntity;
import com.topscomm.pub.util.ConvertUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.xmlbeans.XmlCursor;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;


/**
 * com.topscomm.mpm.utils
 * MengM_
 * 2021/8/11 20:12
 * mpm
 */
public class GenerateAppointmentTemplateUtil extends GenerateWordTemplateUtil {

    private static List<String> specialSymbol = new ArrayList<>();
    static {
        for (int i = 0; i < 10; i++) {
            specialSymbol.add(ConvertUtil.convertToString(i));
        }
    }


    /**
     * 替换word文档中的文本
     *
     * @param paraMap
     * @throws Exception
     */
    public static void readWordFile(Map<String, Object> paraMap, String sourcefilePath, String destFilePath, String fileName) throws Exception {
//        System.out.println("!!!!!!!!!"+ HSSFWorkbook.class.getProtectionDomain().getCodeSource().getLocation());
        File demoFile = new File(sourcefilePath);
        FileInputStream in = new FileInputStream(demoFile);
        XWPFDocument xwpf = new XWPFDocument(in);

        insertParam(paraMap);
        dealParam(paraMap);
        // 替换文本中的占位符
        changeParagraphText(xwpf, paraMap);

        // 替换第一个表格
        changeTableText(xwpf, (List<Map<String, Object>>) paraMap.get("headlist"), xwpf.getTables().get(0), false);
        changeTableText(xwpf, (List<Map<String, Object>>) paraMap.get("sslist"), xwpf.getTables().get(1), false);
        replaceTable(xwpf.getTables().get(3), paraMap);

        // 循环生成剩余的表格
        changeTableText(xwpf, paraMap, xwpf.getTables().get(2));


        OutputStream os = new FileOutputStream(destFilePath + "/" + fileName + ".docx");
        xwpf.write(os);
        closeStream(in);
        closeStream(os);
    }

    private static void insertParam(Map<String, Object> paraMap) {
        if (null == paraMap || paraMap.isEmpty()) {
            return;
        }
        List<Map<String, Object>> headList = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("appointmentnumber", paraMap.get("appointmentnumber"));
        map1.put("signercode", paraMap.get("signercode"));
        headList.add(map1);
        paraMap.put("headlist", headList);
        List<Map<String, Object>> footlist = new ArrayList<>();
        Map<String, Object> map2 = new HashMap<>();
        map2.put("nowdateup", paraMap.get("nowdateup"));
        footlist.add(map2);
        paraMap.put("footlist", footlist);

        // 处理项目组中重复人员
        List<Map<String, Object>> tableList = (List<Map<String, Object>>) paraMap.get("tablelist");
        if (CollectionUtils.isEmpty(tableList)) {
            return;
        }
//        listSortBySortCode(tableList);
        for (Map<String, Object> map : tableList) {
            List<Map<String, Object>> list = (List<Map<String, Object>>) map.get("table");
            if (CollectionUtils.isEmpty(list)) {
                continue;
            }
            listSortByPosition(list);
            // 过滤掉撤销的人员
            list = list.stream().filter(item -> !MpmSystemConst.MPM_TAEM_APPOINTMENTTYPE_REVOKE.equals(item.get("appointmenttype"))).collect(Collectors.toList());
            map.put("table", list);
        }
    }
    public static void listSortBySortCode(List<Map<String, Object>> list) {
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(list)) {
            Collections.sort(list, new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    int sortCodeO1 = ConvertUtil.convertToInt(o1.get("sortcode"));
                    int sortCodeO2 = ConvertUtil.convertToInt(o2.get("sortcode"));
                    if (sortCodeO1 > sortCodeO2) {
                        return 1;
                    }
                    else if (sortCodeO1 < sortCodeO2) {
                        return -1;
                    }
                    else {
                        Date createOn1 = ConvertUtil.convertToDate(o1.get("createon"));
                        Date createOn2 = ConvertUtil.convertToDate(o2.get("createon"));
                        if (createOn1.before(createOn2)) {
                            return -1;
                        }
                        if (createOn2.before(createOn1)) {
                            return 1;
                        }
                        return 0;
                    }
                }
            });
        }
    }

    /**
    * @Description:    根据职位排序
    * @Author:         mengmeng
    * @Date:           2021/9/11 9:38
    * @Version:        1.0
    */
    public static void listSortByPosition(List<Map<String, Object>> list) {
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(list)) {
            Collections.sort(list, new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    String role1 = ConvertUtil.convertToString(o1.get(MpmProjectTeamEntity.FieldProjectrole));
                    String role2 = ConvertUtil.convertToString(o2.get(MpmProjectTeamEntity.FieldProjectrole));
                    int sort1 = ConvertUtil.convertToInt(o2.get(MpmProjectTeamEntity.FieldSortcode));
                    int sort2 = ConvertUtil.convertToInt(o2.get(MpmProjectTeamEntity.FieldSortcode));
                    if (MpmSystemConst.MPM_TEAM_PROJECT_ROLE_LEADER.equals(role1)) {
                        if (MpmSystemConst.MPM_TEAM_PROJECT_ROLE_LEADER.equals(role2)) {
                            // 如果都是组长，则按照排序吗升序排序
                            return sort1 - sort2;
                        }
                        // 如果role2不是组长，role1是组长，则role1放在前面
                        return -1;
                    }
                    else {
                        if (MpmSystemConst.MPM_TEAM_PROJECT_ROLE_LEADER.equals(role2)) {
                            // 如果role2是组长，role1不是组长，则role2放在前面
                            return 1;
                        }
                        // 如果都不是组长，则按排序吗升序排序
                        return sort1 - sort2;
                    }
                }
            });
        }
    }

    private static void dealParam(Map<String, Object> paraMap) {
        if (null == paraMap || paraMap.isEmpty()) {
            return;
        }
        for (Map.Entry<String, Object> entry : paraMap.entrySet()) {
            Object value = entry.getValue();
            if (value instanceof String) {
                paraMap.put(entry.getKey(), fillStr(String.valueOf(value), entry.getKey()));
            }
            if (value instanceof List) {
                List<Map<String, Object>> list = (List<Map<String, Object>>) value;
                for (Map<String, Object> map : list) {
                    dealParam(map);
                }
            }
        }
    }

    private static boolean notChinese(String str) {
        int length = str.length();
        int byteLength = str.getBytes().length;
        return length == byteLength;
    }

    private static String fillStr(String str, String key) {
        if ("appointmentnumber".equals(key) && str.contains("[") && str.contains("]")) {
            return str.replace("[", "【").replace("]", "】");
        }
        // 两个字的名字中间增加空格
        if (("username".equals(key) || "ss".equals(key)) && str.length() == 3 && specialSymbol.contains(str.substring(2))) {
            str = str.substring(0, 2);
            return  str.substring(0, 1) + "  " + str.substring(1);
        }
        if (("username".equals(key) || "ss".equals(key)) && str.length() == 4 && specialSymbol.contains(str.substring(3))) {
            str = str.substring(0, 3);
        }
        if (("username".equals(key) || "ss".equals(key)) && str.length() == 5 && specialSymbol.contains(str.substring(4))) {
            str = str.substring(0, 4);
        }
        if (notChinese(str)) {
            return str;
        }
        if (str.length() != 2) {
            return str;
        }
        return str.substring(0, 1) + "  " + str.substring(1, 2);
    }

    /**
     * @Description:    替换表格中的内容，该方法会删除掉文档中原来的表格，根据原文档中表格中的占位符，使用list列表中的数据替换，生成表格的行数会根据list的size决定
     * @Author:         mengmeng
     *                  withHead: true表示新生成的表格有表头， false表示没有表头
     * @Date:           2021/8/11 9:25
     * @Version:        1.0
     */
    public static void changeTableText(XWPFDocument document, Map<String, Object> textMap, XWPFTable table) {
        // 获取当前表格前面的paragraph
        int posOfTable = document.getPosOfTable(table);
        XWPFParagraph paragraphArray = document.getParagraphArray(posOfTable);


        List<Map<String, Object>> tableList = (List<Map<String, Object>>) textMap.get("tablelist");
        for (Map<String, Object> map : tableList) {
            List<Map<String, Object>> mapList = (List<Map<String, Object>>) map.get("table");
            // 如果组员是空的，项目组也不展示
            if (CollectionUtils.isEmpty(mapList)) {
                continue;
            }
            // 在当前paragraph获得节点，创建一个新的table
            XmlCursor cursor = paragraphArray.getCTP().newCursor();
            XWPFTable newCreateTable = document.insertNewTbl(cursor);
            newCreateTable.getCTTbl().setTblPr(table.getCTTbl().getTblPr());

            // 表格标题行
            XWPFTableRow newCreateRow = newCreateTable.createRow();
            CopyTableRow(newCreateRow, table.getRow(0));// 复制行
            replaceTableRow(newCreateRow, map);
            // 循环生成表格内容行
            for (Map<String, Object> map1 : mapList) {
                XWPFTableRow newCreateRow1 = newCreateTable.createRow();
                CopyTableRow(newCreateRow1, table.getRow(1));// 复制模板行
                replaceTableRow(newCreateRow1, map1);// 处理标签替换
            }
            newCreateTable.removeRow(0);// 移除多出来的第一行
            document.insertNewParagraph( paragraphArray.getCTP().newCursor());
        }


        document.removeBodyElement(posOfTable);
        document.removeBodyElement(posOfTable);
        document.removeBodyElement(posOfTable);
        document.createParagraph();// 添加回车换行
    }
    public static void changeTableText1(XWPFDocument document, List<Map<String, Object>> list, XWPFTable table, boolean withHead) {
        int posOfTable = document.getPosOfTable(table);
        // 获取当前表格前面的paragraph
        XWPFParagraph paragraphArray = document.getLastParagraph();

        // 在当前paragraph获得节点，创建一个新的table
        XmlCursor cursor = paragraphArray.getCTP().newCursor();
        XWPFTable newCreateTable = document.insertNewTbl(cursor);
        newCreateTable.getCTTbl().setTblPr(table.getCTTbl().getTblPr());

        if (withHead) {
            // 复制表头
            XWPFTableRow newCreateRow = newCreateTable.createRow();
            CopyTableRow(newCreateRow, table.getRow(0));// 复制行
        }

        for (int i = 0; i < list.size(); i++) {
            XWPFTableRow newCreateRow1 = newCreateTable.createRow();
            CopyTableRow(newCreateRow1, table.getRow(withHead ? 1 : 0));// 复制模板行
            replaceTableRow(newCreateRow1, list.get(i));// 处理标签替换
        }

        document.removeBodyElement(posOfTable);
        newCreateTable.removeRow(0);// 移除多出来的第一行
        document.createParagraph();// 添加回车换行
    }
}
